/*
 * Copyright (c) 2011, Michael van der Westhuizen
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    - Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    - Redistributions in binary form must reproduce the above
 *      copyright notice, this list of conditions and the following
 *      disclaimer in the documentation and/or other materials provided
 *      with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#ifndef PYXMLSEC1_BN_C_MCVDW_20110104
#define PYXMLSEC1_BN_C_MCVDW_20110104

#include "pyxmlsec.h"

#include <xmlsec/bn.h>



static PyObject * xmlsec1_xmlSecBnCreate(PyObject * self, PyObject * args, PyObject * kwds)
{
    xmlSecBnPtr bn;
    int size_;
    xmlSecSize size;
    PyObject * obj;

    static char * kwlist[] = {"size", NULL};
    bn = NULL;
    size_ = 0;
    size = 0;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &size_))
    {
        return NULL;
    }

    size = size_;

    if (NULL == (bn = xmlSecBnCreate(size)))
    {
        ENSURE_EXCEPTION_SET(xmlSecBnCreate);
        return NULL;
    }

    if (NULL == (obj = xmlsec1mod_wrap_xmlSecBnPtr(bn)))
    {
        ENSURE_EXCEPTION_SET(xmlsec1mod_wrap_xmlSecBnPtr);
        xmlSecBnDestroy(bn);
        return NULL;
    }

    return obj;
}



static PyObject * xmlsec1_xmlSecBnDestroy(PyObject * self, PyObject * arg)
{
    xmlSecBnPtr bn;

    if (NULL == (bn = xmlsec1mod_unwrap_xmlSecBnPtr(arg)))
    {
        return NULL;
    }

    xmlSecBnDestroy(bn);
    Py_RETURN_NONE;
}



static PyObject * xmlsec1_xmlSecBnInitialize(PyObject * self, PyObject * args, PyObject * kwds)
{
    xmlSecBnPtr bn;
    PyObject * obj;
    int size_;
    xmlSecSize size;

    static char * kwlist[] = {"bn", "size", NULL};

    bn = NULL;
    obj = NULL;
    size_ = 0;
    size = 0;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oi", kwlist, &obj, &size_))
    {
        return NULL;
    }

    size = size_;

    if (NULL == (bn = xmlsec1mod_unwrap_xmlSecBnPtr(obj)))
    {
        return NULL;
    }

    xmlSecBnFinalize(bn);

    if (0 != xmlSecBnInitialize(bn, size))
    {
        ENSURE_EXCEPTION_SET(xmlSecBnInitialize);
        return NULL;
    }

    Py_RETURN_NONE;
}



static PyObject * xmlsec1_xmlSecBnFinalize(PyObject * self, PyObject * arg)
{
    xmlSecBnPtr bn;

    if (NULL == (bn = xmlsec1mod_unwrap_xmlSecBnPtr(arg)))
    {
        return NULL;
    }

    xmlSecBnFinalize(bn);
    Py_RETURN_NONE;
}



static PyObject * xmlsec1_xmlSecBnGetSize(PyObject * self, PyObject * arg)
{
    xmlSecBnPtr bn;

    if (NULL == (bn = xmlsec1mod_unwrap_xmlSecBnPtr(arg)))
    {
        return NULL;
    }

    return PyInt_FromLong((long)xmlSecBnGetSize(bn));
}



static PyObject * xmlsec1_xmlSecBnZero(PyObject * self, PyObject * arg)
{
    xmlSecBnPtr bn;

    if (NULL == (bn = xmlsec1mod_unwrap_xmlSecBnPtr(arg)))
    {
        return NULL;
    }

    xmlSecBnZero(bn);
    Py_RETURN_NONE;
}



static PyObject * xmlsec1_xmlSecBnGetData(PyObject * self, PyObject * arg)
{
    xmlSecBnPtr bn;

    if (NULL == (bn = xmlsec1mod_unwrap_xmlSecBnPtr(arg)))
    {
        return NULL;
    }

    return PyByteArray_FromStringAndSize((const char *)xmlSecBnGetData(bn), xmlSecBnGetSize(bn));
}



static PyObject * xmlsec1_xmlSecBnReverse(PyObject * self, PyObject * arg)
{
    xmlSecBnPtr bn;

    if (NULL == (bn = xmlsec1mod_unwrap_xmlSecBnPtr(arg)))
    {
        return NULL;
    }

    if (0 != xmlSecBnReverse(bn))
    {
        ENSURE_EXCEPTION_SET(xmlSecBnReverse);
        return NULL;
    }

    Py_RETURN_NONE;
}



static PyObject * xmlsec1_xmlSecBnToHexString(PyObject * self, PyObject * arg)
{
    xmlSecBnPtr bn;
    xmlChar * ptr;
    PyObject * ret;

    if (NULL == (bn = xmlsec1mod_unwrap_xmlSecBnPtr(arg)))
    {
        return NULL;
    }

    if (NULL == (ptr = xmlSecBnToHexString(bn)))
    {
        ENSURE_EXCEPTION_SET(xmlSecBnToHexString);
        return NULL;
    }

    if (NULL == (ret = PyString_FromString((const char *)ptr)))
    {
        ENSURE_EXCEPTION_SET(PyString_FromString);
        xmlFree(ptr);
        return NULL;
    }

    xmlFree(ptr);
    return ret;
}



static PyObject * xmlsec1_xmlSecBnToDecString(PyObject * self, PyObject * arg)
{
    xmlSecBnPtr bn;
    xmlChar * ptr;
    PyObject * ret;

    if (NULL == (bn = xmlsec1mod_unwrap_xmlSecBnPtr(arg)))
    {
        return NULL;
    }

    if (NULL == (ptr = xmlSecBnToDecString(bn)))
    {
        ENSURE_EXCEPTION_SET(xmlSecBnToDecString);
        return NULL;
    }

    if (NULL == (ret = PyString_FromString((const char *)ptr)))
    {
        ENSURE_EXCEPTION_SET(PyString_FromString);
        xmlFree(ptr);
        return NULL;
    }

    xmlFree(ptr);
    return ret;
}



static PyObject * xmlsec1_xmlSecBnSetData(PyObject * self, PyObject * args, PyObject * kwds)
{
    xmlSecBnPtr bn;
    PyObject * obj;
    PyObject * data_;
    xmlSecByte * data;
    xmlSecSize size;

    static char * kwlist[] = {"bn", "data", NULL};

    bn = NULL;
    obj = data_ = NULL;
    data = NULL;
    size = 0;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &obj, &data_))
    {
        return NULL;
    }

    if (NULL == (bn = xmlsec1mod_unwrap_xmlSecBnPtr(obj)))
    {
        return NULL;
    }

    if (0 != xmlsec1_ByteArrayOrBytesToXmlSecBytes(data_, &data, &size))
    {
        return NULL;
    }

    if (0 != xmlSecBnSetData(bn, data, size))
    {
        ENSURE_EXCEPTION_SET(xmlSecBnInitialize);
        PyMem_Del(data);
        return NULL;
    }

    PyMem_Del(data);
    Py_RETURN_NONE;
}



static PyObject * xmlsec1_xmlSecBnFromString(PyObject * self, PyObject * args, PyObject * kwds)
{
    xmlSecBnPtr bn;
    PyObject * obj;
    char * data_;
    int base_;
    xmlChar * data;
    xmlSecSize base;

    static char * kwlist[] = {"bn", "s", "base", NULL};

    bn = NULL;
    obj = NULL;
    data_ = NULL;
    base_ = 10;
    data = NULL;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "Os|i", kwlist, &obj, &data_, &base_))
    {
        return NULL;
    }

    if (NULL == (bn = xmlsec1mod_unwrap_xmlSecBnPtr(obj)))
    {
        return NULL;
    }

    if (NULL == (data = xmlCharStrdup(data_)))
    {
        return PyErr_NoMemory();
    }

    base = (xmlSecSize)base_;

    if (0 != xmlSecBnFromString(bn, data, base))
    {
        ENSURE_EXCEPTION_SET(xmlSecBnFromString);
        xmlFree(data);
        return NULL;
    }

    xmlFree(data);
    Py_RETURN_NONE;
}



static PyObject * xmlsec1_xmlSecBnToString(PyObject * self, PyObject * args, PyObject * kwds)
{
    xmlSecBnPtr bn;
    PyObject * obj;
    PyObject * data;
    int base_;
    xmlChar * data_;
    xmlSecSize base;

    static char * kwlist[] = {"bn", "base", NULL};

    bn = NULL;
    obj = data = NULL;
    data_ = NULL;
    base_ = 10;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &obj, &base_))
    {
        return NULL;
    }

    if (NULL == (bn = xmlsec1mod_unwrap_xmlSecBnPtr(obj)))
    {
        return NULL;
    }

    base = (xmlSecSize)base_;

    if (NULL == (data_ = xmlSecBnToString(bn, base)))
    {
        ENSURE_EXCEPTION_SET(xmlSecBnToString);
        return NULL;
    }

    data = PyString_FromString((const char *)data_);
    xmlFree(data_);
    return data;
}



static PyObject * xmlsec1_xmlSecBnFromHexString(PyObject * self, PyObject * args, PyObject * kwds)
{
    xmlSecBnPtr bn;
    PyObject * obj;
    char * data_;
    xmlChar * data;

    static char * kwlist[] = {"bn", "s", NULL};

    bn = NULL;
    obj = NULL;
    data_ = NULL;
    data = NULL;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "Os", kwlist, &obj, &data_))
    {
        return NULL;
    }

    if (NULL == (bn = xmlsec1mod_unwrap_xmlSecBnPtr(obj)))
    {
        return NULL;
    }

    if (NULL == (data = xmlCharStrdup(data_)))
    {
        return PyErr_NoMemory();
    }

    if (0 != xmlSecBnFromHexString(bn, data))
    {
        ENSURE_EXCEPTION_SET(xmlSecBnFromHexString);
        xmlFree(data);
        return NULL;
    }

    xmlFree(data);
    Py_RETURN_NONE;
}



static PyObject * xmlsec1_xmlSecBnFromDecString(PyObject * self, PyObject * args, PyObject * kwds)
{
    xmlSecBnPtr bn;
    PyObject * obj;
    char * data_;
    xmlChar * data;

    static char * kwlist[] = {"bn", "s", NULL};

    bn = NULL;
    obj = NULL;
    data_ = NULL;
    data = NULL;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "Os", kwlist, &obj, &data_))
    {
        return NULL;
    }

    if (NULL == (bn = xmlsec1mod_unwrap_xmlSecBnPtr(obj)))
    {
        return NULL;
    }

    if (NULL == (data = xmlCharStrdup(data_)))
    {
        return PyErr_NoMemory();
    }

    if (0 != xmlSecBnFromDecString(bn, data))
    {
        ENSURE_EXCEPTION_SET(xmlSecBnFromDecString);
        xmlFree(data);
        return NULL;
    }

    xmlFree(data);
    Py_RETURN_NONE;
}



static PyObject * xmlsec1_xmlSecBnMul(PyObject * self, PyObject * args, PyObject * kwds)
{
    xmlSecBnPtr bn;
    PyObject * obj;
    int multiplier;

    static char * kwlist[] = {"bn", "multiplier", NULL};

    bn = NULL;
    obj = NULL;
    multiplier = 0;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oi", kwlist, &obj, &multiplier))
    {
        return NULL;
    }

    if (NULL == (bn = xmlsec1mod_unwrap_xmlSecBnPtr(obj)))
    {
        return NULL;
    }

    if (0 != xmlSecBnMul(bn, multiplier))
    {
        ENSURE_EXCEPTION_SET(xmlSecBnMul);
        return NULL;
    }

    Py_RETURN_NONE;
}



static PyObject * xmlsec1_xmlSecBnAdd(PyObject * self, PyObject * args, PyObject * kwds)
{
    xmlSecBnPtr bn;
    PyObject * obj;
    int delta;

    static char * kwlist[] = {"bn", "delta", NULL};

    bn = NULL;
    obj = NULL;
    delta = 0;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oi", kwlist, &obj, &delta))
    {
        return NULL;
    }

    if (NULL == (bn = xmlsec1mod_unwrap_xmlSecBnPtr(obj)))
    {
        return NULL;
    }

    if (0 != xmlSecBnAdd(bn, delta))
    {
        ENSURE_EXCEPTION_SET(xmlSecBnAdd);
        return NULL;
    }

    Py_RETURN_NONE;
}



static PyObject * xmlsec1_xmlSecBnDiv(PyObject * self, PyObject * args, PyObject * kwds)
{
    xmlSecBnPtr bn;
    PyObject * obj;
    int divider;
    int mod;

    static char * kwlist[] = {"bn", "divider", NULL};

    bn = NULL;
    obj = NULL;
    divider = 0;
    mod = 0;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oi", kwlist, &obj, &divider))
    {
        return NULL;
    }

    if (NULL == (bn = xmlsec1mod_unwrap_xmlSecBnPtr(obj)))
    {
        return NULL;
    }

    if (0 != xmlSecBnDiv(bn, divider, &mod))
    {
        ENSURE_EXCEPTION_SET(xmlSecBnDiv);
        return NULL;
    }

    return PyInt_FromLong((long)mod);
}



static PyObject * xmlsec1_xmlSecBnCompare(PyObject * self, PyObject * args, PyObject * kwds)
{
    xmlSecBnPtr bn;
    PyObject * obj1;
    PyObject * obj2;
    xmlSecByte * data;
    xmlSecSize dataSize;
    int ret;

    static char * kwlist[] = {"bn", "data", NULL};

    bn = NULL;
    obj1 = NULL;
    obj2 = NULL;
    data = NULL;
    dataSize = 0;
    ret = 0;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &obj1, &obj2))
    {
        return NULL;
    }

    if (NULL == (bn = xmlsec1mod_unwrap_xmlSecBnPtr(obj1)))
    {
        return NULL;
    }

    if (0 != xmlsec1_ByteArrayOrBytesToXmlSecBytes(obj2, &data, &dataSize))
    {
        return NULL;
    }

    ret = xmlSecBnCompare(bn, data, dataSize);
    PyMem_Del(data);
    return PyInt_FromLong((long)ret);
}



static PyObject * xmlsec1_xmlSecBnCompareReverse(PyObject * self, PyObject * args, PyObject * kwds)
{
    xmlSecBnPtr bn;
    PyObject * obj1;
    PyObject * obj2;
    xmlSecByte * data;
    xmlSecSize dataSize;
    int ret;

    static char * kwlist[] = {"bn", "data", NULL};

    bn = NULL;
    obj1 = NULL;
    obj2 = NULL;
    data = NULL;
    dataSize = 0;
    ret = 0;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &obj1, &obj2))
    {
        return NULL;
    }

    if (NULL == (bn = xmlsec1mod_unwrap_xmlSecBnPtr(obj1)))
    {
        return NULL;
    }

    if (0 != xmlsec1_ByteArrayOrBytesToXmlSecBytes(obj2, &data, &dataSize))
    {
        return NULL;
    }

    ret = xmlSecBnCompareReverse(bn, data, dataSize);
    PyMem_Del(data);
    return PyInt_FromLong((long)ret);
}



static PyObject * xmlsec1_xmlSecBnGetNodeValue(PyObject * self, PyObject * args, PyObject * kwds)
{
    xmlSecBnPtr bn;
    PyObject * obj1;
    PyObject * obj2;
    xmlNodePtr cur;
    int format;
    int reverse;

    static char * kwlist[] = {"bn", "cur", "format", "reverse", NULL};

    bn = NULL;
    obj1 = obj2 = NULL;
    cur = NULL;
    format = reverse = 0;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOii", kwlist, &obj1, &obj2, &format, &reverse))
    {
        return NULL;
    }

    if (NULL == (bn = xmlsec1mod_unwrap_xmlSecBnPtr(obj1)))
    {
        return NULL;
    }

    if (NULL == (cur = xmlsec1mod_unwrap_xmlNodePtr(obj2)))
    {
        return NULL;
    }

    if (0 != xmlSecBnGetNodeValue(bn, cur, (xmlSecBnFormat)format, reverse))
    {
        ENSURE_EXCEPTION_SET(xmlSecBnGetNodeValue);
        return NULL;
    }

    Py_RETURN_NONE;
}



static PyObject * xmlsec1_xmlSecBnSetNodeValue(PyObject * self, PyObject * args, PyObject * kwds)
{
    xmlSecBnPtr bn;
    PyObject * obj1;
    PyObject * obj2;
    xmlNodePtr cur;
    int format;
    int reverse;
    int addLineBreaks;

    static char * kwlist[] = {"bn", "cur", "format", "reverse", "addLineBreaks", NULL};

    bn = NULL;
    obj1 = obj2 = NULL;
    cur = NULL;
    format = reverse = addLineBreaks = 0;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOiii", kwlist, &obj1, &obj2, &format, &reverse, &addLineBreaks))
    {
        return NULL;
    }

    if (NULL == (bn = xmlsec1mod_unwrap_xmlSecBnPtr(obj1)))
    {
        return NULL;
    }

    if (NULL == (cur = xmlsec1mod_unwrap_xmlNodePtr(obj2)))
    {
        return NULL;
    }

    if (0 != xmlSecBnSetNodeValue(bn, cur, (xmlSecBnFormat)format, reverse, addLineBreaks))
    {
        ENSURE_EXCEPTION_SET(xmlSecBnSetNodeValue);
        return NULL;
    }

    Py_RETURN_NONE;
}



static PyObject * xmlsec1_xmlSecBnBlobSetNodeValue(PyObject * self, PyObject * args, PyObject * kwds)
{
    xmlSecByte * data;
    xmlSecSize dataSize;
    PyObject * obj1;
    PyObject * obj2;
    xmlNodePtr cur;
    int format;
    int reverse;
    int addLineBreaks;

    static char * kwlist[] = {"data", "cur", "format", "reverse", "addLineBreaks", NULL};

    data = NULL;
    dataSize = 0;
    obj1 = obj2 = NULL;
    cur = NULL;
    format = reverse = addLineBreaks = 0;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOiii", kwlist, &obj1, &obj2, &format, &reverse, &addLineBreaks))
    {
        return NULL;
    }

    if (0 != xmlsec1_ByteArrayOrBytesToXmlSecBytes(obj1, &data, &dataSize))
    {
        return NULL;
    }

    if (NULL == (cur = xmlsec1mod_unwrap_xmlNodePtr(obj2)))
    {
        PyMem_Del(data);
        return NULL;
    }

    if (0 != xmlSecBnBlobSetNodeValue(data, dataSize, cur, (xmlSecBnFormat)format, reverse, addLineBreaks))
    {
        ENSURE_EXCEPTION_SET(xmlSecBnBlobSetNodeValue);
        PyMem_Del(data);
        return NULL;
    }

    PyMem_Del(data);
    Py_RETURN_NONE;
}

#endif
